上一篇我們聊到了 Vue 的檔案結構,我們用現實生活中的東西來比喻這些檔案。今天我們就來講講作為「積木」的 Component。
如果你對 HTML5 語意化標籤(header、nav、footer...)熟悉的話,Component 的概念就不會太陌生。我們可以將這些區分成 一個又一個 Component。例如 Navbar.vue、Footer.vue、Navber.vue,而當開發者寫完這些組件後,就可以在頁面的 vue 檔案中匯入。
想像一下,如果開發者全部都把功能和組件寫在同一個檔案,那檔案可能會長到上千行,在維護的時候一定會不方便,減少「可維護性」。另外,如果一個頁面有上千上萬個 code,也會減少「可讀性」,增加掛掉的風險。因此,我們會把這些功能給分開來。假設開發者寫了一個名為「Card」的組件,那開發者就可以在 App.vue 或是其他頁面的 vue 檔案 import 進來,並且可以重複使用多次,也符合「可重複性」。
Component 通常會寫在 src/components/
底下,每一個檔案都是 .vue
檔案。我們用一個例子舉例,假設開發者需要寫一個卡片的 Vue,那麼開發者就會在這個資料夾底下,創一個新的資料夾,即 src/components/Card/
。在這個檔案底下,再建立一個 Card.vue
或 index.vue
,即 src/components/Card/Card.vue
或 src/components/Card/index.vue
。
因此你可以將其看成是一層一層的,App.vue 作為最初進入點,再來是 [page_name].vue,再來是 Component。
當然,開發者也可以使用多個 component 結構,例如:
/src/components/Card/index.vue
/src/components/Card/Card_large.vue(從 index.vue 引入)
/src/components/Card/Card_medium.vue(從 index.vue 引入)
/src/components/Card/Card_small.vue(從 index.vue 引入)
Card_[Size].vue 可以從 index.vue 引入共用的邏輯或標籤及元件,達到一致性。
當您想使用 Component 的時候,我們可以在 components 資料夾建立,以 Card 為例,當您建立好之後,可以輸入以下的程式碼:
<script setup lang="ts">
</script>
<template>
<p style="padding: 20px; border: 1px solid red;">我愛鐵人賽</p>
</template>
然後讀者就可以在 App.vue
內引入:
<script setup lang="ts">
import Card from './components/Card/Card.vue'
</script>
<template>
<Card />
</template>
因此讀者就可以在網站上面看到這個組件。
當然,您也可以依照「可重複性」:
<script setup lang="ts">
import Card from './components/Card/Card.vue'
</script>
<template>
<Card />
<Card />
<Card />
<Card />
<Card />
</template>
然後讀者就可以在網頁上看到五個。
讀者也可以修改成開發者可以修改的版本:Card.vue
:
<script setup lang="ts">
import { ref } from 'vue'
defineProps<{ msg: string }>()
</script>
<template>
<p style="padding: 20px; border: 1px solid red;">{{ msg }}</p>
</template>
App.vue
:
<script setup lang="ts">
import Card from './components/Card/Card.vue'
</script>
<template>
<Card msg="鐵人賽" />
<Card msg="我好愛" />
<Card msg="Vue" />
<Card msg="前端" />
<Card msg="TypeScript" />
</template>
這邊有一個新的概念,就是 Props & Emit,這是我們第一次用到 Props,讓父元件(App.vue)能把資料傳給子元件(Card.vue),本文我們就不會先介紹了。
我們來做一張簡單的「個人名片卡片」,上面要有名字、年齡、工作三個資訊。這個範例會讓你更直觀感受到 Component 的重複使用性。
思路解析:
/src/components/Card/Card.vue
Card.vue
的 程式碼App.vue
匯入 Card.vue
。Card.vue:
<template>
<div class="card">
<h2>{{ name }}</h2>
<p>年齡:{{ age }}</p>
<p>職業:{{ job }}</p>
</div>
</template>
<script setup lang="ts">
defineProps<{
name: string
age: number
job: string
}>()
</script>
<style scoped>
.card {
border: 1px solid #ccc;
padding: 16px;
border-radius: 8px;
width: 200px;
margin: 10px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
h2 {
margin: 0 0 8px 0;
font-size: 20px;
color: #333;
}
p {
margin: 4px 0;
font-size: 14px;
color: #555;
}
</style>
App.vue:
<script setup lang="ts">
import Card from './components/Card/Card.vue'
</script>
<template>
<div style="display: flex; gap: 10px; flex-wrap: wrap;">
<Card name="小明" :age="18" job="學生" />
<Card name="小華" :age="25" job="前端工程師" />
<Card name="小美" :age="30" job="設計師" />
</div>
</template>
雖然今天我們提及了少少的 Props,但我們沒有提到非常深入,未來我們會詳細深入聊到 Props 和 Emit。也許讀者有發現到,我們在開發 Vue,大多都是在開發 Component。因此你也可以說我們寫前端,就是再組積木,將積木一片一片拼起來,是不是很有趣呢?下一章我們要講 Composition API 及 Option API 的差別。